import {
	Color,
	PolylineArrowMaterialProperty,
	PolygonHierarchy,
	Cartesian3,
	Cartesian4,
	PostProcessStage,
	HeadingPitchRange,
	CallbackProperty,
	Math as cesiumMath,
	Rectangle,
	NearFarScalar,
	ColorMaterialProperty,
	Transforms,
	Matrix4,
	Cartographic,
	Cartesian2,
	ImageMaterialProperty,
	LineFlowMaterialProperty,
	Ellipsoid,
} from "cesium";

/**
 * @description: 产生随机点
 * @param {*} position：中心点坐标
 * @param {*} num：随机点数量
 * @return {*}
 */
export const generateRandomPosition = (position, num) => {
	let list = [];
	for (let i = 0; i < num; i++) {
		// random产生的随机数范围是0-1，需要加上正负模拟
		let lon = position[0] + Math.random() * 0.04 * (i % 2 == 0 ? 1 : -1);
		let lat = position[1] + Math.random() * 0.04 * (i % 2 == 0 ? 1 : -1);
		list.push([lon, lat]);
	}
	return list;
};

/**
 * @description: 竖直随机飞线初始化
 * @param {*} _viewer
 * @param {*} _center ：中心点
 * @param {*} _num ：数量
 * @return {*}
 */
export const lineFlowInit = (_viewer, _center, _num) => {
	let _positions = generateRandomPosition(_center, _num);
	_positions.forEach((item) => {
		console.log("item------------------");
		console.log(item);

		// 经纬度
		let start_lon = item[0];
		let start_lat = item[1];

		let startPoint = new Cartesian3.fromDegrees(start_lon, start_lat, 0);

		// 随机高度
		let height = 5000 * Math.random();
		let endPoint = new Cartesian3.fromDegrees(start_lon, start_lat, height);
		let linePositions = [];
		linePositions.push(startPoint);
		linePositions.push(endPoint);
		_viewer.entities.add({
			polyline: {
				positions: linePositions,
				material: new LineFlowMaterialProperty({
					color: new Color(1.0, 1.0, 0.0, 0.8),
					speed: 15 * Math.random(),
					percent: 0.1,
					gradient: 0.01,
				}),
			},
		});
	});
};

/**
 * @description: 抛物飞线效果初始化
 * @param {*} _viewer 当前viewer单独UI西安昂
 * @param {*} _num :每条线上的飞线数量
 * @return {*}
 */

export const parabolaFlowInit = (_viewer, _num) => {
	let _center = [113.26826367882262, 23.1381520242615];
	let _positions = [
		[113.244807, 23.144568],
		[113.312938, 23.129189],
		[113.300935, 23.143839],
		[113.822965, 23.283922],
		[113.526148, 22.80173],
		[113.344075, 23.145948],
		[113.271455, 23.112136],
		[113.269087, 23.202798],
		[113.376456, 23.124494],
		[113.245139, 23.087279],
		[113.278683, 23.13052],
		[113.318869, 23.166055],
		[113.316116, 23.098584],
		[113.383898, 22.948387],
		[113.244873, 23.282587],
		[113.404638, 23.385404],
		[113.358788, 23.294487],
		[113.299237, 23.347044],
		[113.275543, 23.154549],
		[113.373932, 23.112827],
		[113.605399, 23.12292],
		[113.215333, 23.385054],
		[113.273491, 23.436141],
		[113.321506, 23.436262],
		[113.181741, 23.454722],
		[113.870389, 23.771835],
		[113.589175, 23.543664],
		[113.418954, 23.622731],
		[113.678424, 23.63371],
		[113.431474, 23.169309],
		[113.495299, 23.150867],
		[113.277926, 23.080252],
		[113.273426, 23.127829],
		[113.525878, 23.059446],
		[113.457836, 23.107109],
		[113.45653, 23.105514],
		[113.428128, 23.076534],
		[113.273836, 23.170145],
		[113.218163, 23.395116],
		[113.106668, 23.335404],
		[113.060928, 23.395699],
		[113.291789, 23.556733],
		[113.280284, 23.458391],
		[113.591187, 23.549468],
		[113.487265, 22.969647],
		[113.733069, 23.722228],
		[113.824317, 23.284843],
		[113.78594, 23.418958],
		[113.616589, 23.28853],
		[113.792079, 23.178072],
		[113.894637, 23.416335],
		[113.78524, 23.488541],
	];
	_positions.forEach((item) => {
		let _siglePositions = parabola(_center, item, 5000);
		// 创建飞线
		for (let i = 0; i < _num; i++) {
			_viewer.entities.add({
				polyline: {
					positions: _siglePositions,
					material: new LineFlowMaterialProperty({
						color: new Color(1.0, 1.0, 0.0, 0.8),
						speed: 1 * Math.random(),
						percent: 0.1,
						gradient: 0.01,
					}),
				},
			});
		}
		// 创建轨迹线
		_viewer.entities.add({
			polyline: {
				positions: _siglePositions,
				material: new PolylineArrowMaterialProperty(new Color(1.0, 1.0, 0.0, 0.5)),
			},
		});
	});
};

/**
 * @description: 抛物线构造函数
 * @param {startPositionstartPosition}  开始点位
 * @param {endPosition} endPosition 结束点位
 * @param {height} height 抛物线高度
 * @return {*}
 */
export const parabola = (startPosition, endPosition, height = 5000, count = 50) => {
	//方程 y=-(4h/L^2)*x^2+h h:顶点高度 L：横纵间距较大者
	let result = [];
	height = Math.max(+height, 100);
	count = Math.max(+count, 50);
	let diffLon = Math.abs(startPosition[0] - endPosition[0]);
	let diffLat = Math.abs(startPosition[1] - endPosition[1]);
	let L = Math.max(diffLon, diffLat);
	let dlt = L / count;
	if (diffLon > diffLat) {
		//base on lon
		let delLat = (endPosition[1] - startPosition[1]) / count;
		if (startPosition[0] - endPosition[0] > 0) {
			dlt = -dlt;
		}
		for (let i = 0; i < count; i++) {
			let h = height - (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * height) / Math.pow(L, 2);
			let lon = startPosition[0] + dlt * i;
			let lat = startPosition[1] + delLat * i;
			let point = new Cartesian3.fromDegrees(lon, lat, h);
			result.push(point);
		}
	} else {
		//base on lat
		let delLon = (endPosition[0] - startPosition[0]) / count;
		if (startPosition[1] - endPosition[1] > 0) {
			dlt = -dlt;
		}
		for (let i = 0; i < count; i++) {
			let h = height - (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * height) / Math.pow(L, 2);
			let lon = startPosition[0] + delLon * i;
			let lat = startPosition[1] + dlt * i;
			let point = new Cartesian3.fromDegrees(lon, lat, h);
			result.push(point);
		}
	}
	return result;
};

/**
 * circleDiffusion：圆扩散
 * 参考gitee上的ts代码
 */

// 圆扩散
export class CircleDiffusion {
	constructor(viewer) {
		this.viewer = viewer;
		this.lastStageList = [];
		// js语法的每行结尾的“分号”可写可不写
	}
	add(position, scanColor, maxRadius, duration) {
		this.lastStageList.push(this.showCircleScan(position, scanColor, maxRadius, duration));
	}
	clear() {
		this.lastStageList.forEach((ele) => {
			this.clearScanEffects(ele);
		});
		this.lastStageList = [];
	}
	/**
	 * 圆扩散
	 * @param {*} position  扫描中心 如[117.270739,31.84309,32]
	 * @param {*} scanColor 扫描颜色 如"rgba(0,255,0,1)"
	 * @param {*} maxRadius 扫描半径，单位米 如1000米
	 * @param {*} duration 持续时间，单位毫秒 如4000
	 */
	showCircleScan(position, scanColor, maxRadius, duration) {
		const cartographicCenter = new Cartographic(cesiumMath.toRadians(position[0]), cesiumMath.toRadians(position[1]), position[2]);
		scanColor = new Color.fromCssColorString(scanColor);
		const lastStage = this._addCircleScanPostStage(cartographicCenter, maxRadius, scanColor, duration);
		return lastStage;
	}
	/**
	 * 添加扩散效果扫描线
	 * @param {*} cartographicCenter  扫描中心
	 * @param {*} maxRadius 扫描半径
	 * @param {*} scanColor  扫描颜色
	 * @param {*} duration  持续时间
	 */
	_addCircleScanPostStage(cartographicCenter, maxRadius, scanColor, duration) {
		const _Cartesian3Center = Cartographic.toCartesian(cartographicCenter);
		const _Cartesian4Center = new Cartesian4(_Cartesian3Center.x, _Cartesian3Center.y, _Cartesian3Center.z, 1);
		const _CartograhpicCenter1 = new Cartographic(cartographicCenter.longitude, cartographicCenter.latitude, cartographicCenter.height + 500);
		const _Cartesian3Center1 = Cartographic.toCartesian(_CartograhpicCenter1);
		const _Cartesian4Center1 = new Cartesian4(_Cartesian3Center1.x, _Cartesian3Center1.y, _Cartesian3Center1.z, 1);
		const _time = new Date().getTime();
		const _scratchCartesian4Center = new Cartesian4();
		const _scratchCartesian4Center1 = new Cartesian4();
		const _scratchCartesian3Normal = new Cartesian3();
		const _this = this;
		const ScanPostStage = new PostProcessStage({
			fragmentShader: _this._getScanSegmentShader(),
			uniforms: {
				u_scanCenterEC: function () {
					const temp = Matrix4.multiplyByVector(_this.viewer.camera._viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
					return temp;
				},
				u_scanPlaneNormalEC: function () {
					const temp = Matrix4.multiplyByVector(_this.viewer.camera._viewMatrix, _Cartesian4Center, _scratchCartesian4Center);
					const temp1 = Matrix4.multiplyByVector(_this.viewer.camera._viewMatrix, _Cartesian4Center1, _scratchCartesian4Center1);
					_scratchCartesian3Normal.x = temp1.x - temp.x;
					_scratchCartesian3Normal.y = temp1.y - temp.y;
					_scratchCartesian3Normal.z = temp1.z - temp.z;
					Cartesian3.normalize(_scratchCartesian3Normal, _scratchCartesian3Normal);
					return _scratchCartesian3Normal;
				},
				u_radius: function () {
					return (maxRadius * ((new Date().getTime() - _time) % duration)) / duration;
				},
				u_scanColor: scanColor,
			},
		});
		this.viewer.scene.postProcessStages.add(ScanPostStage);
		return ScanPostStage;
	}
	/**
	 * 扩散效果Shader
	 */
	_getScanSegmentShader() {
		const inpram = 18;
		const scanSegmentShader =
			` uniform sampler2D colorTexture;
          uniform sampler2D depthTexture;
          varying vec2 v_textureCoordinates;
          uniform vec4 u_scanCenterEC;
          uniform vec3 u_scanPlaneNormalEC;
          uniform float u_radius;
          uniform vec4 u_scanColor;
          vec4 toEye(in vec2 uv, in float depth){
            vec2 xy = vec2((uv.x * 2.0 - 1.0),(uv.y * 2.0 - 1.0));
            vec4 posInCamera = czm_inverseProjection * vec4(xy, depth, 1.0);
            posInCamera =posInCamera / posInCamera.w;
            return posInCamera;
          }
          vec3 pointProjectOnPlane(in vec3 planeNormal, in vec3 planeOrigin, in vec3 point){
              vec3 v01 = point - planeOrigin;
              float d = dot(planeNormal, v01) ;
              return (point - planeNormal * d);
          }
          float getDepth(in vec4 depth){
              float z_window = czm_unpackDepth(depth);
              z_window = czm_reverseLogDepth(z_window);
              float n_range = czm_depthRange.near;
              float f_range = czm_depthRange.far;
              return (2.0 * z_window - n_range - f_range) / (f_range - n_range);
          }
          void main(){
              gl_FragColor = texture2D(colorTexture, v_textureCoordinates);
              float depth = getDepth(texture2D(depthTexture, v_textureCoordinates));
              vec4 viewPos = toEye(v_textureCoordinates, depth);
              vec3 prjOnPlane = pointProjectOnPlane(u_scanPlaneNormalEC.xyz, u_scanCenterEC.xyz, viewPos.xyz);
              float dis = length(prjOnPlane.xyz - u_scanCenterEC.xyz);
              if(dis < u_radius){
                float f = 1.0 - abs(u_radius - dis) / u_radius;
                f = pow(f, float(` +
			inpram +
			`));
                gl_FragColor = mix(gl_FragColor,u_scanColor,f);
              }
              gl_FragColor.a = gl_FragColor.a / 2.0;
          }
        `;
		return scanSegmentShader;
	}
	/**
	 * 清除特效对象
	 * @param {*} lastStage 特效对象
	 */
	clearScanEffects(lastStage) {
		this.viewer.scene.postProcessStages.remove(lastStage);
	}
}

/**
 * @Description： 立体雷达扫描效果
 * @viewer {Object} viewer对象
 * @radius {number} 圆角
 * @color {number} 颜色对象
 * @speed {number} 旋转速度
 * @position {Array} 经纬度坐标
 */
export const radarSolidScan = ({ viewer, radius, color, speed, position } = {}) => {
	let thisData = {};
	thisData._viewer = options.viewer;
	// 半径
	thisData._radius = options.radius;
	// 扫描扇形颜色
	thisData._color = options.color;
	// 扫描速度
	thisData._speed = options.speed;
	// 中心点坐标经纬度
	thisData._cenLon = options.position[0];
	thisData._cenLat = options.position[1];
	// 先建立椭球体
	thisData._viewer.entities.add({
		position: new Cartesian3.fromDegrees(thisData._cenLon, thisData._cenLat),
		name: "立体雷达扫描",
		ellipsoid: {
			radii: new Cartesian3(thisData._radius, thisData._radius, thisData._radius),
			material: thisData._color,
			outline: true,
			outlineColor: thisData._color,
			outlineWidth: 1,
		},
	});

	let heading = 0,
		positionArr = calculatePane(thisData._cenLon, thisData._cenLat, 1000.0, heading);
	// 每一帧刷新时调用
	thisData._viewer.clock.onTick.addEventListener(() => {
		heading += thisData._speed;
		positionArr = calculatePane(thisData._cenLon, thisData._cenLat, 1000.0, heading);
	});

	// 创建1/4圆形立体墙
	let radarWall = thisData._viewer.entities.add({
		wall: {
			positions: new CallbackProperty(() => {
				return Cartesian3.fromDegreesArrayHeights(positionArr);
			}, false),
			material: Color.RED,
		},
	});

	// 计算平面扫描范围
	function calculatePane(x1, y1, radius, heading) {
		var m = Transforms.eastNorthUpToFixedFrame(Cartesian3.fromDegrees(x1, y1));
		var rx = radius * Math.cos((heading * Math.PI) / 180.0);
		var ry = radius * Math.sin((heading * Math.PI) / 180.0);
		var translation = Cartesian3.fromElements(rx, ry, 0);
		var d = Matrix4.multiplyByPoint(m, translation, new Cartesian3());
		var c = Cartographic.fromCartesian(d);
		var x2 = cesiumMath.toDegrees(c.longitude);
		var y2 = cesiumMath.toDegrees(c.latitude);
		return calculateSector(x1, y1, x2, y2);
	}

	// 计算竖直扇形
	function calculateSector(x1, y1, x2, y2) {
		let positionArr = [];
		positionArr.push(x1);
		positionArr.push(y1);
		positionArr.push(0);
		var radius = Cartesian3.distance(Cartesian3.fromDegrees(x1, y1), Cartesian3.fromDegrees(x2, y2));
		// 扇形是1/4圆，因此角度设置为0-90
		for (let i = 0; i <= 90; i++) {
			let h = radius * Math.sin((i * Math.PI) / 180.0);
			let r = Math.cos((i * Math.PI) / 180.0);
			let x = (x2 - x1) * r + x1;
			let y = (y2 - y1) * r + y1;
			positionArr.push(x);
			positionArr.push(y);
			positionArr.push(h);
		}
		return positionArr;
	}
};

/**
 * @name 动态圆扩散
 * @minR {number} 最小半径
 * @maxR {number} 最大半径
 * @deviationR {number} 每次增加半径大小
 * @position {Array} 经纬度
 */
export const dynamicCircle = ({ minR, maxR, deviationR, position } = {}) => {
	minR = minR ? minR : 100;
	let minData = minR;
	maxR = maxR ? maxR : 5000;
	deviationR = deviationR ? deviationR : 50;
	position = position ? position : [113.89263931497018, 22.76474442946943];
	function changeR1() {
		minR = minR + deviationR; //deviationR为每次圆增加的大小
		if (minR >= maxR) {
			minR = minData;
		}
		return minR;
	}
	function colorSet() {
		let x = 1 - minR / maxR;
		return Color.RED.withAlpha(x);
	}
	function changeR() {
		return minR;
	}
	let image = ``;
	let entity = viewer.entities.add({
		position: Cartesian3.fromDegrees(position[0], position[1]),
		name: "圆形",
		ellipse: {
			semiMinorAxis: new CallbackProperty(changeR, false),
			semiMajorAxis: new CallbackProperty(changeR1, false),
			material: new ImageMaterialProperty({
				repeat: new Cartesian2(1.0, 1.0),
				image: image,
				transparent: true,
				color: new CallbackProperty(colorSet, false),
			}),
			show: false,
			// material: new ColorMaterialProperty(new CallbackProperty(color,false)),
			outlineColor: Color.RED,
		},
	});
};

export const getCenterPosition = (viewer) => {
	let centerResult = viewer.camera.pickEllipsoid(new Cartesian2(viewer.canvas.clientWidth / 2, viewer.canvas.clientHeight / 2));
	let curPosition = Ellipsoid.WGS84.cartesianToCartographic(centerResult);
	let curLongitude = (curPosition.longitude * 180) / Math.PI;
	let curLatitude = (curPosition.latitude * 180) / Math.PI;
	console.log({
		lon: curLongitude,
		lat: curLatitude,
	});
	return {
		lon: curLongitude,
		lat: curLatitude,
	};
};
